﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using InvoiceInvoker.Logic.Repositories;
using InvoiceInvoker.Logic;

namespace InvoiceInvoker.MvcUI.Controllers
{
	[Authorize]
	[HandleError]
	public class InvoiceEditorController : Controller
	{
		private int _sellerId;
		private RegisteredCustomerRepository _customerRepository;
		private RegisteredProductRepository _productRepository;

		protected override void OnActionExecuting(ActionExecutingContext filterContext)
		{
			_sellerId = (int)Session["SellerId"];
			_customerRepository = new RegisteredCustomerRepository(_sellerId);
			_productRepository = new RegisteredProductRepository(_sellerId);

			base.OnActionExecuting(filterContext);
		}

		[HttpPost]
		public ActionResult GetCustomer(int id)
		{
			RegisteredCustomer customer = _customerRepository.GetById(id);

			var data = new
			{
				CustomerName = customer.CustomerName,
				CompanyName = customer.CompanyName,
				Street = customer.Street,
				City = customer.City,
				PostalCode = customer.PostalCode,
				Nip = customer.Nip
			};

			return Json(data);
		}

		[HttpGet]
		public ActionResult FilterProducts(string q)
		{
			List<RegisteredProduct> products = _productRepository.GetByName(q);

			string[] contents = new string[products.Count];

			for (int i = 0; i != products.Count; i++)
				contents[i] = products[i].Name + "|" + products[i].Id.ToString();

			return Content(string.Join("\n", contents));
		}

		[HttpPost]
		public ActionResult GetProduct(int id)
		{
			RegisteredProduct product = _productRepository.GetById(id);

			var data = new
			{
				Id = product.Id,
				Name = product.Name,
				Pkwiu = product.Pkwiu,
				MeasureUnit = product.MeasureUnit,
				NetPrice = product.NetPrice.Value.ToString("N"),
				VatRate = product.VatRate
			};

			return Json(data);
		}

		[HttpPost]
		public ActionResult UpdateProductValues(int id, string quantity)
		{
			Dictionary<int, decimal> productQuantities = Session["ProductQuantities"] as Dictionary<int, decimal>;
			decimal quantityValue;

			if (decimal.TryParse(quantity, out quantityValue) && quantityValue > 0)
			{
				productQuantities[id] = quantityValue;

				Product product = _productRepository.GetById(id).ToProduct(quantityValue);
				
				var data = new
				{
					Id = id,
					NetValue = product.NetValue.Value.ToString("N"),
					VatValue = product.VatValue.Value.ToString("N"),
					GrossValue = product.GrossValue.Value.ToString("N")
				};

				return Json(data);
			}
			else
			{
				productQuantities[id] = 0;

				var data = new
				{
					Id = id,
					NetValue = "błąd",
					VatValue = "błąd",
					GrossValue = "błąd"
				};

				return Json(data);
			}
			
		}

		[HttpPost]
		public ActionResult AddProductToPattern(int id)
		{
			List<int> productIds = Session["ProductIds"] as List<int>;

			if (id == 0 || productIds.Contains(id))
				return Json(null);

			productIds.Add(id);

			RegisteredProduct product = _productRepository.GetById(id);

			var data = new
			{
				Id = product.Id,
				Name = product.Name,
				Pkwiu = product.Pkwiu,
				MeasureUnit = product.MeasureUnit,
				NetPrice = product.NetPrice.Value.ToString("N"),
				VatRate = product.VatRate
			};

			return Json(data);
		}

		[HttpPost]
		public ActionResult AddProductToInvoice(int id, decimal quantity)
		{
			List<int> productIds = Session["ProductIds"] as List<int>;
			Dictionary<int, decimal> productQuantities = Session["ProductQuantities"] as Dictionary<int, decimal>;

			if (id == 0 || productIds.Contains(id))
				return Json(null);

			productIds.Add(id);
			productQuantities[id] = quantity;

			Product product = _productRepository.GetById(id).ToProduct(quantity);

			var data = new
			{
				Id = id,
				Name = product.Name,
				Pkwiu = product.Pkwiu,
				MeasureUnit = product.MeasureUnit,
				Quantity = product.Quantity.Value.ToString("N"),
				NetPrice = product.NetPrice.Value.ToString("N"),
				NetValue = product.NetValue.Value.ToString("N"),
				VatRate = product.VatRate,
				VatValue = product.VatValue.Value.ToString("N"),
				GrossValue = product.GrossValue.Value.ToString("N")
			};

			return Json(data);
		}

		[HttpPost]
		public ActionResult RemoveProductFromPattern(int id)
		{
			List<int> productIds = Session["ProductIds"] as List<int>;
			productIds.Remove(id);

			return null;
		}

		[HttpPost]
		public ActionResult RemoveProductFromInvoice(int id)
		{
			List<int> productIds = Session["ProductIds"] as List<int>;
			Dictionary<int, decimal> productQuantities = Session["ProductQuantities"] as Dictionary<int, decimal>;

			productIds.Remove(id);
			productQuantities.Remove(id);

			return null;
		}

		[HttpPost]
		public ActionResult GetGeneralValues()
		{
			List<int> productIds = Session["ProductIds"] as List<int>;
			Dictionary<int, decimal> productQuantities = Session["ProductQuantities"] as Dictionary<int, decimal>;

			List<Product> products = new List<Product>();

			foreach (int id in productIds)
				products.Add(_productRepository.GetById(id).ToProduct(productQuantities[id]));

			decimal toPay = products.Sum(p => p.GrossValue).Value;

			List<string> allVatRates = VatRatesProvider.GetVatRates();
			List<string> vatRates = new List<string>();

			vatRates.Add("X");

			foreach (string vatRate in allVatRates)
			{
				if (products.Any(p => p.VatRate == vatRate))
					vatRates.Add(vatRate);
			}

			string[] netValues = new string[vatRates.Count];
			string[] vatValues = new string[vatRates.Count];
			string[] grossValues = new string[vatRates.Count];

			netValues[0] = products.Sum(p => p.NetValue).Value.ToString("N");
			vatValues[0] = products.Sum(p => p.VatValue).Value.ToString("N");
			grossValues[0] = toPay.ToString("N");

			for (int i = 1; i != vatRates.Count; i++)
			{
				List<Product> currentProducts = products.Where(p => p.VatRate == vatRates[i]).ToList();
				netValues[i] = currentProducts.Sum(p => p.NetValue).Value.ToString("N");
				vatValues[i] = currentProducts.Sum(p => p.VatValue).Value.ToString("N");
				grossValues[i] = currentProducts.Sum(p => p.GrossValue).Value.ToString("N");
			}

			var data = new
			{
				ToPay = toPay.ToString("F"),
				VatRates = vatRates.ToArray(),
				NetValues = netValues,
				VatValues = vatValues,
				GrossValues = grossValues
			};

			return Json(data);
		}

		[HttpPost]
		public ActionResult GetToPayInWords(string toPay, string currency)
		{
			decimal toPayValue;

			if (decimal.TryParse(toPay, out toPayValue))
				return Json(new { result = NumberToWordsConverter.ConvertMoney(toPayValue, currency) });
			else
				return Json(new { result = "błąd" });
		}

		[HttpPost]
		public ActionResult GetLeftToPay(string toPay, string paid)
		{
			decimal toPayValue;
			decimal paidValue;

			if (decimal.TryParse(toPay, out toPayValue) && decimal.TryParse(paid, out paidValue))
				return Json(new { result = (toPayValue - paidValue).ToString("F") });
			else
				return Json(new { result = "błąd" });
		}
	}
}
